package models

import (
	"fmt"
	"github.com/EDDYCJY/go-gin-app/pkg/setting"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
	"log"
	"time"
)

var db *gorm.DB

type Model struct {
	ID int `gorm:"primary_key" json:"id"`
	CreatedOn int `json:"created_on"`
	ModifiedOn int `json:"modified_on"`
	DeletedOn int `json:"deleted_on"`
}

func Setup() {
	var err error
	//var (
	//	err error
	//	dbType,dbName,user,password,host,tablePrefix string
	//)
	//
	//sec,err := setting.Cfg.GetSection("database")
	//if err !=nil {
	//	log.Fatal(2,"fail to get database : %v", err)
	//}
	dbType := setting.DatabaseSetting.Type
	dbName := setting.DatabaseSetting.Name
	user := setting.DatabaseSetting.User
	password := setting.DatabaseSetting.Password
	host := setting.DatabaseSetting.Host
	tablePrefix := setting.DatabaseSetting.TablePrefix

	db,err = gorm.Open(dbType,fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8&parseTime=True&loc=Local",
		user,
		password,
		host,
		dbName))
	if err != nil {
		log.Fatalln(err)
	}
	gorm.DefaultTableNameHandler = func(db *gorm.DB, defaultTableName string) string {
		return tablePrefix + defaultTableName
	}
	db.SingularTable(true)
	db.LogMode(true)
	db.DB().SetMaxIdleConns(10)
	db.DB().SetMaxOpenConns(100)
	db.Callback().Create().Replace("gorm:update_time_stamp", updateTimesStampForCreateCallback)
	db.Callback().Update().Replace("gorm:update_time_stamp", updateTimeStampForUpdateCallback)
	db.Callback().Delete().Replace("gorm:delete", deletedCallback)
}

func CloseDb()  {
	defer db.Close()
}

/**
新增记录的时候写入创建时间与更新时间
 */
func updateTimesStampForCreateCallback(scope *gorm.Scope)  {
	if !scope.HasError() {
		nowTime := time.Now().Unix()
		if createdTimeField,ok := scope.FieldByName("CreatedOn");ok {
			if createdTimeField.IsBlank {
				createdTimeField.Set(nowTime)
			}
		}

		if modifiedTimeField,ok := scope.FieldByName("ModifiedOn");ok {
			if modifiedTimeField.IsBlank {
				modifiedTimeField.Set(nowTime)
			}
		}
	}
}
/**
更新记录的时候写入更新时间
 */
// updateTimeStampForUpdateCallback will set `ModifyTime` when updating
func updateTimeStampForUpdateCallback(scope *gorm.Scope) {
	if _, ok := scope.Get("gorm:update_column"); !ok {
		scope.SetColumn("ModifiedOn", time.Now().Unix())
	}
}

/**

 */
func deletedCallback(scope *gorm.Scope)  {
	if !scope.HasError() {
		var extraOption string
		if str,ok := scope.Get("gorm:delete_option");ok {
			extraOption = fmt.Sprint(str)
		}
		deletedOnField, hasDeletedOnField := scope.FieldByName("DeletedOn")
		if !scope.Search.Unscoped && hasDeletedOnField {
			scope.Raw(fmt.Sprintf(
				"UPDATE %v SET %v=%v%v%v",
				scope.QuotedTableName(),
				scope.Quote(deletedOnField.DBName),
				scope.AddToVars(time.Now().Unix()),
				addExtraSpaceIfExist(scope.CombinedConditionSql()),
				addExtraSpaceIfExist(extraOption),
			)).Exec()
		} else {
			scope.Raw(fmt.Sprintf(
				"DELETE FROM %v%v%v",
				scope.QuotedTableName(),
				addExtraSpaceIfExist(scope.CombinedConditionSql()),
				addExtraSpaceIfExist(extraOption),
			)).Exec()
		}
	}
}

func addExtraSpaceIfExist(str string) string {
	if str != "" {
		return " " + str
	}
	return ""
}